package com.dream.wukong.common.core.importexport.csv.rest;

import com.alibaba.fastjson.JSON;
import com.dream.wukong.common.core.db.mybatis.support.BaseServiceImpl;
import com.dream.wukong.common.core.importexport.csv.CsvExport;
import com.dream.wukong.common.core.importexport.csv.CsvImport;
import com.dream.wukong.common.core.importexport.csv.config.CsvConfiguration;
import com.dream.wukong.common.core.importexport.csv.config.CsvTable;
import com.dream.wukong.common.core.importexport.csv.impl.CsvImportImpl;
import com.dream.wukong.common.core.importexport.csv.impl.ImportResult;
import com.dream.wukong.common.core.importexport.excel.ExcelImportImpl;
import com.dream.wukong.common.core.importexport.excel.ExcleExport;
import com.dream.wukong.common.core.importexport.pdf.PdfExport;
import com.dream.wukong.common.core.util.StringUtil;
import com.dream.wukong.common.core.util.WebUtils;
import com.dream.wukong.common.core.web.ServiceResult;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FileUtils;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
 * @Author: wuyichao
 * @Description:
 * @Date: Created in 16:37 2018/9/17.
 * @Modified:
 */
@RestController
public class ImportExportController {

    private static final Logger logger = LoggerFactory.getLogger(ImportExportController.class);


    @Resource(name = "csvImport")
    protected CsvImport csvImport;

    @Resource(name = "csvConfig")
    protected CsvConfiguration csvConfig;

    @Resource(name = "excleImport")
    protected ExcelImportImpl excleImport;

    @Resource(name = "csvExport")
    protected CsvExport csvExport;

    @Resource(name = "pdfExport")
    protected PdfExport pdfExport;

    @Resource(name = "excleExport")
    protected ExcleExport excleExport;

    ///////导出
    @ApiOperation(value = "通用的表格导出方法", notes = "通用的表格导出方法")
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public void export(
            @RequestParam String tableId,
            @RequestParam(required = false) List<Integer> options,
            @RequestParam(required = false, defaultValue = "csv") String exportType,
            @RequestParam Map<String, Object> param,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        logger.debug("导出rest方法 ,查询参数：" + param );
        // 1.从DB获取数据
        List<T> list = Lists.newArrayList();

        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId);
        fields = this.expandFields(request, fields);
        // 2.写入临时文件
        File tempDir = WebUtils.getTempDir(request.getServletContext());
        File tmpFile = null;
        if ("pdf".equalsIgnoreCase(exportType)) {
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".pdf");
            if (options != null) {
                pdfExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                pdfExport.expToFile(list, tableId, tmpFile, fields);
            }
        }else if("Excle".equalsIgnoreCase(exportType)){
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".xls");
            if (options != null) {
                excleExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                excleExport.expToFile(list, tableId, tmpFile, fields);
            }
        } else {
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".csv");
            if (options != null) {
                csvExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                csvExport.expToFile(list, tableId, tmpFile, fields);
            }
        }
        logger.debug("生成文件存储位置:" + tmpFile.getAbsolutePath());
        // 3.下载
        InputStream in = new FileInputStream(tmpFile);
        WebUtils.download(response, in, tmpFile.getName());
    }



    /***
     * 描  述: 导入rest方法
     * 参  数:file
     * 参  数:tableId
     * 参  数:request
     * 返回值: com.hollycrm.hollybeacons.system.web.ServiceResult
     * 创建时间: 2018/7/23
     */
    @ApiOperation(value = "通用的导入方法", notes = "通用的导入方法", response = ServiceResult.class)
    @RequestMapping(value = "/import", method = RequestMethod.POST)
    public ServiceResult baseImport(@RequestParam MultipartFile file,
                                    @RequestParam Map<String, Object> param,
                                    @RequestParam String tableId, HttpServletRequest request)
            throws Exception {
        logger.debug("导入rest方法 , tableId：" + tableId );
        // 1.保存到临时文件中
        InputStream in = file.getInputStream();
        File tempDir = WebUtils.getTempDir(request.getServletContext());
        File tmpFile = null;
        ImportResult result = null;
        //获取service
        CsvImportImpl.setBaseServiceImpl(new BaseServiceImpl());

        if(null != param && !param.isEmpty()){
            Map<String, String[]> parameterMap = request.getParameterMap();
            Set<String> keys = param.keySet();
            for(String key : keys){
                Object o = param.get(key);
                try {
                    parameterMap.put(key,new String[]{o.toString()});
                }catch (Exception e){

                }
            }
        }

        CsvImportImpl.setRequest(request);

        if(file.getOriginalFilename().contains("csv")){
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".csv");
            FileUtils.copyInputStreamToFile(in, tmpFile);
            // 2.导入到数据库中
            result = csvImport.impToDb(tmpFile, tableId);
        }else{
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".xls");
            FileUtils.copyInputStreamToFile(in, tmpFile);
            // 2.导入到数据库中
            result = excleImport.impToDb(tmpFile, tableId);
        }

        return createSuccessResult(result);
    }


    /***
     * 描  述: sql形式导出rest方法
     * 参  数:file
     * 参  数:tableId
     * 参  数:request
     * 返回值: com.hollycrm.hollybeacons.system.web.ServiceResult
     * 创建时间: 2018/7/23
     */
    @ApiOperation(value = "通用sql的导出方法", notes = "通用的导出方法", response = ServiceResult.class)
    @RequestMapping(value = "/sqlexport", method = RequestMethod.POST)
    public void sqlexport(
            @RequestParam String tableId,
            @RequestParam(required = false) List<Integer> options,
            @RequestParam(required = false, defaultValue = "csv") String exportType,
            @RequestParam(required = false) String sqlKey,
            @RequestParam Map<String, Object> param,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        logger.debug("查询参数 param:" + param);

        // 1.从DB获取数据
        List<T> list = Lists.newArrayList();
        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId);

        fields = this.expandFields(request, fields);
        // 2.写入临时文件
        File tempDir = WebUtils.getTempDir(request.getServletContext());
        File tmpFile = null;
        if ("pdf".equalsIgnoreCase(exportType)) {
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".pdf");
            if (options != null) {
                pdfExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                pdfExport.expToFile(list, tableId, tmpFile, fields);
            }
        } else if("Excle".equalsIgnoreCase(exportType)){
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".xls");
            if (options != null) {
                excleExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                excleExport.expToFile(list, tableId, tmpFile, fields);
            }
        } else {
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".csv");
            if (options != null) {
                csvExport.expToFile(list, tableId, tmpFile, fields, options);
            } else {
                csvExport.expToFile(list, tableId, tmpFile, fields);
            }
        }
        logger.debug("生成文件存储位置:" + tmpFile.getAbsolutePath());
        // 3.下载

        InputStream in = new FileInputStream(tmpFile);
        WebUtils.download(response, in, tmpFile.getName());
//        return createSuccessResult(tmpFile.getName());
    }


    ///调用基类统一的导入列表方法
    @ApiOperation(value = "通用的导入列表方法", notes = "通用的导入列表方法", response = ServiceResult.class)
    @RequestMapping(value = "/sqlimport", method = RequestMethod.POST, produces = "text/html;charset=utf-8")
    public void sqlimport(@RequestParam MultipartFile file,
                          @RequestParam Map<String, Object> param,
                          @RequestParam String tableId, HttpServletRequest request ,HttpServletResponse response)
            throws Exception {
        // 1.保存到临时文件中
        CsvImportImpl.setRequest(request);
        InputStream in = file.getInputStream();
        File tempDir = WebUtils.getTempDir(request.getServletContext());
        File tmpFile = null;
        ImportResult result = null;
        //获取service
        CsvImportImpl.setBaseServiceImpl(new BaseServiceImpl());

        if(null != param && !param.isEmpty()){
            Map<String, String[]> parameterMap = request.getParameterMap();
            Set<String> keys = param.keySet();
            for(String key : keys){
                Object o = param.get(key);
                try {
                    parameterMap.put(key,new String[]{o.toString()});
                }catch (Exception e){

                }
            }
        }

        CsvImportImpl.setRequest(request);

        if(file.getOriginalFilename().contains("csv")){
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".csv");
            FileUtils.copyInputStreamToFile(in, tmpFile);
            // 2.导入到数据库中
            result = csvImport.impToDb(tmpFile, tableId);
        }else{
            tmpFile = new File(tempDir, UUID.randomUUID().toString() + ".xls");
            FileUtils.copyInputStreamToFile(in, tmpFile);
            // 2.导入到数据库中
            result = excleImport.impToDb(tmpFile, tableId);
        }

        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(createSuccessResult(result)));
        out.flush();
        out.close();

//        return createSuccessResult(result);
    }

    /////不符合导入规则的数据下载
    @ApiOperation(value = "通用的不符合导入规则的数据下载", notes = "通用的不符合导入规则的数据下载")
    @RequestMapping(value = "/invalid/download" , method = RequestMethod.GET)
    public void downloadInvalidData( @RequestParam String filename, HttpServletRequest request, HttpServletResponse response)
            throws Exception{
        ///////////////因目前没有分布式文件存储系统，暂时只完成功能，只支持单节点，等有文件系统后将文件推送到文件系统后进行下载
        File tempDir = WebUtils.getTempDir(request.getServletContext());
        File tmpFile = new File(tempDir, filename);
        WebUtils.download(response, new FileInputStream(tmpFile), filename,request);
    }


    //导入模板下载
    @ApiOperation(value = "通用的导入模板下载", notes = "通用的导入模板下载")
    @RequestMapping(value = "/template/download", method = RequestMethod.GET)
    public void downloadTemplate(@RequestParam String tableId,
                                 @RequestParam(required=false) String fileName,
                                 @RequestParam(required = false, defaultValue = "csv") String type,
                                 HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        File tempDir = WebUtils.getTempDir(request.getServletContext());
        String fileType = type.equals("csv")?".csv":".xls";
        File tmpFile = new File(tempDir, UUID.randomUUID().toString() + fileType);
        if(StringUtil.isNotEmpty(fileName)){
            tmpFile = new File(tempDir, fileName + fileType);
        }
        if(type.equals("csv")){
            csvImport.getImportTemplate(tableId, tmpFile);
        }else{
            excleImport.getImportTemplate(tableId, tmpFile);
        }

        // 2.下载
        logger.debug("生成导入模板文件存储位置:" + tmpFile.getAbsolutePath());
        InputStream in = new FileInputStream(tmpFile);

        WebUtils.download(response, in, "导入模板"+fileType,request);
    }


//    /////CSV导入向导页
//    @ApiOperation(value = "通用的CSV导入列表方法", notes = "通用的CSV导入列表方法", response = ServiceResult.class)
//    @RequestMapping(value = "/wizard/import",method = RequestMethod.GET)
//    public ServiceResult importWizard(@RequestParam String tableId,
//                             @RequestParam Map<String, Object> param,
//                             HttpServletRequest request, HttpServletResponse response)
//            throws Exception {
//        CsvTable csvTable = csvConfig.getCsvTable(tableId);
//        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
//        List<? extends CsvTable.CsvField> fields = csvConfig.getImportedCsvFields(tableId);
//        return createSuccessResult(fields);
//    }

    ////CSV SQL导入向导页
    @ApiOperation(value = "通用的CSV导入列表方法", notes = "通用的CSV导入列表方法", response = ServiceResult.class)
    @RequestMapping(value = "/wizard/sqlimport",method = RequestMethod.GET)
    public ServiceResult sqlImportWizard(@RequestParam String tableId,
                                         @RequestParam Map<String, Object> param,
                                         HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        CsvTable csvTable = csvConfig.getCsvTable(tableId);
        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
        List<? extends CsvTable.CsvField> fields = csvConfig.getImportedCsvFields(tableId);
        return createSuccessResult(fields);
    }

//    @ApiOperation(value = "通用的CSV导出列表方法", notes = "通用的CSV导出列表方法", response = ServiceResult.class)
//    @RequestMapping(value = "/wizard/export",method = RequestMethod.GET)
//    public ServiceResult exportWizard(@RequestParam String tableId,
//                             @RequestParam Map<String, Object> param,
//                             HttpServletRequest request, HttpServletResponse response)
//            throws Exception {
//        CsvTable csvTable = csvConfig.getCsvTable(tableId);
//        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
//        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId);
////        this.expandWizardFields(request,fields);
////        Object exportType = param.get("exportMode");
////        exportType = exportType == null ? "csv" : exportType;
////        request.setAttribute("exportMode", exportType);
//
//        return createSuccessResult(fields);
//    }

    @ApiOperation(value = "通用的CSV导出列表方法", notes = "通用的CSV导出列表方法", response = ServiceResult.class)
    @RequestMapping(value = "/wizard/sqlexport",method = RequestMethod.GET)
    public ServiceResult sqlexportWizard(@RequestParam String tableId,
                                         @RequestParam Map<String, Object> param,
                                         HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        CsvTable csvTable = csvConfig.getCsvTable(tableId);
        Assert.notNull(csvTable, tableId + "对应的csvTable配置不存在");
        List<? extends CsvTable.CsvField> fields = csvConfig.getExportedCsvFields(tableId) ;
//        this.expandWizardFields(request,fields);
//        Object exportType = param.get("exportMode");
//        exportType = exportType == null ? "csv" : exportType;
//        request.setAttribute("exportMode", exportType);
        return createSuccessResult(fields);
    }

    protected ServiceResult createSuccessResult(Object content) {
        ServiceResult serviceResult = new ServiceResult();

        return serviceResult;
    }


    protected ServiceResult createFailResult(String errmsg) {
        ServiceResult serviceResult = new ServiceResult();

        return serviceResult;
    }

    //////子类可进行二次扩展
    protected List<? extends CsvTable.CsvField> expandFields(HttpServletRequest request, List<? extends CsvTable.CsvField> fields){
        return fields;
    }
}
